home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / kernel / timer / sun4c.md / timerSun4c.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-12-19  |  10.6 KB  |  438 lines

  1. /* 
  2.  * timerSun4c.c --
  3.  *
  4.  *    This file contains the routines that control the time of day clock 
  5.  *    and interrupt timers on the sun4c (SparcStation 1) machine. The
  6.  *    sun4c contains a Mostek MK48T12-15 chip for time of day and 
  7.  *    two interrupt timers.  
  8.  *
  9.  *    Until we get the data sheets for the Mostek chip, we use the interrupt
  10.  *    counters for both interupts and TOD.
  11.  *
  12.  * Copyright 1989 Regents of the University of California
  13.  * Permission to use, copy, modify, and distribute this
  14.  * software and its documentation for any purpose and without
  15.  * fee is hereby granted, provided that the above copyright
  16.  * notice appear in all copies.  The University of California
  17.  * makes no representations about the suitability of this
  18.  * software for any purpose.  It is provided "as is" without
  19.  * express or implied warranty.
  20.  */
  21.  
  22. #ifndef lint
  23. static char rcsid[] = "$Header: /cdrom/src/kernel/Cvsroot/kernel/timer/sun4c.md/timerSun4c.c,v 1.10 91/10/18 01:17:25 dlong Exp $ SPRITE (Berkeley)";
  24. #endif /* not lint */
  25.  
  26. #include "sprite.h"
  27. #include "sys.h"
  28. #include "timer.h"
  29. #include "timerInt.h"
  30. #include "timerTick.h"
  31. #include "spriteTime.h"
  32. #include "mach.h"
  33. #include "machMon.h"
  34. #include "prof.h"
  35. #include "stdio.h"
  36.  
  37. #include "timerMK48T12Int.h"
  38.  
  39. #define abs(x) ((x) >= 0 ? (x) : -(x))
  40.  
  41. /*
  42.  * The sun4c contains two counters that count up to value in the limit 
  43.  * register and interrupt. The counters are defined by the following 
  44.  * structure. (Campus-1 Programmer's Model Version 7.5 page 11).
  45.  * We assign counter0 to be the call back interrupt timer and 
  46.  * counter1 to be the profile interrupt timer. Each counter and limit
  47.  * register is of the form:
  48.  *    struct {
  49.  *       int    limitReached :1; -- 1 if counter reached limit. 
  50.  *       int  value         :21; -- Value updated every microsecond. 
  51.  *       int  zeros         :10; -- Read as zero. 
  52.  *     }
  53.  */
  54.  
  55. typedef struct {
  56.     unsigned int callBackCounter; /* Call back counter */
  57.     unsigned int callBackLimit;   /* Limit register for call back counter. */
  58.     unsigned int profileCounter;  /* Profile counter. */
  59.     unsigned int profileLimit;    /* Limit register for profile counter. */
  60. } Counters;
  61.  
  62. /*
  63.  * COUNTER_SHIFT    - Number of bits to shift microsecond value for
  64.  *              counter. 
  65.  * COUNTER_LIMIT_REACH  - Bit signifying count has reached limit.
  66.  */
  67. #define    COUNTER_SHIFT 10
  68. #define    COUNTER_LIMIT_REACH 0x80000000
  69.  
  70. static volatile Counters *counterPtr = (volatile Counters *)NIL;
  71.  
  72. /*
  73.  * The "free running counter"
  74.  */
  75. static Timer_Ticks todCounter;
  76.  
  77. int Timer_TimerServiceInterrupt();
  78.  
  79. /*
  80.  * Timer interval as a Time value. This is the period between callbacks.
  81.  */
  82.  
  83. static Time time = { 0, TIMER_CALLBACK_INTERVAL_APPROX};
  84.  
  85.  
  86. /* 
  87.  *----------------------------------------------------------------------
  88.  *
  89.  * Timer_TimerInit --
  90.  *
  91.  *    Initialize the periodic timer. Since there is no way to turn off
  92.  *    the counters will wait and do all the work in Timer_TimerStart().
  93.  *
  94.  *
  95.  * Results:
  96.  *    None.
  97.  *
  98.  * Side effects:
  99.  *    The timer is initialized.
  100.  *
  101.  *----------------------------------------------------------------------
  102.  */
  103. /*ARGSUSED*/
  104. void
  105. Timer_TimerInit(timer)
  106.     unsigned short     timer;
  107.     if (counterPtr == (volatile Counters *)NIL) {
  108.     if (Mach_MonSearchProm("counter-timer", "address",
  109.         (char *)&counterPtr,
  110.         sizeof counterPtr) !=  sizeof counterPtr) {
  111.         panic("The counter-timer address is missing!\n");
  112.     }
  113.     printf("PROM: Counter-timer is at %x\n", counterPtr);
  114.     }
  115.     if (timer == TIMER_CALLBACK_TIMER) {
  116.     Mach_SetHandler(10, Timer_TimerServiceInterrupt, (ClientData) timer); 
  117.     } else if (timer == TIMER_PROFILE_TIMER) {
  118.     Mach_SetHandler(14, Timer_TimerServiceInterrupt, (ClientData) timer); 
  119.     } else {
  120.     panic("Timer_TimerInit: unknown timer %d\n", timer);
  121.     }
  122. }
  123.  
  124.  
  125. /*
  126.  *----------------------------------------------------------------------
  127.  *
  128.  * Timer_TimerStart --
  129.  *
  130.  *    Loads the specified timer with a new value to count from
  131.  *    and starts the timer.
  132.  *
  133.  *    N.B. The timer must have been initialized with Timer_TimerInit
  134.  *    before this routine is called.
  135.  *
  136.  * Results:
  137.  *    None.
  138.  *
  139.  * Side effects:
  140.  *    The timer starts ticking.
  141.  *
  142.  *----------------------------------------------------------------------
  143.  */
  144.  
  145. void
  146. Timer_TimerStart(timer)
  147.     register unsigned short timer;
  148. {
  149.     unsigned int junk;
  150.  
  151.     /*
  152.      * To start the timer we load the limit register with the correct 
  153.      * count and clear any pending interrupt. 
  154.      */
  155.      if (timer == TIMER_CALLBACK_TIMER) {
  156.      counterPtr->callBackLimit =
  157.              ((TIMER_CALLBACK_INTERVAL_APPROX) << COUNTER_SHIFT);
  158.      junk = counterPtr->callBackLimit;
  159.      DISABLE_INTR();
  160.      *Mach_InterruptReg |= MACH_ENABLE_COUNTER0_INTR_LEVEL;
  161.      ENABLE_INTR();
  162.  
  163.      } else if (timer == TIMER_PROFILE_TIMER) {
  164.      counterPtr->profileLimit =
  165.              ((TIMER_PROFILE_INTERVAL_APPROX) << COUNTER_SHIFT);
  166.      junk = counterPtr->profileLimit;
  167.          DISABLE_INTR();
  168.      *Mach_InterruptReg |= MACH_ENABLE_COUNTER1_INTR_LEVEL;
  169.      ENABLE_INTR();
  170.      } else {
  171.     panic("Timer_TimerInit: unknown timer %d\n", timer);
  172.      }
  173. #ifdef lint
  174.     junk = junk;
  175. #endif
  176.  
  177.  
  178. }
  179.  
  180.  
  181.  
  182. /*
  183.  *----------------------------------------------------------------------
  184.  *
  185.  * Timer_TimerInactivate --
  186.  *
  187.  *    Stops the timer so that it will not cause interrupts.
  188.  *
  189.  * Results:
  190.  *    None.
  191.  *
  192.  * Side effects:
  193.  *    The timer is stopped.
  194.  *
  195.  *----------------------------------------------------------------------
  196.  */
  197.  
  198. void
  199. Timer_TimerInactivate(timer)
  200.     register unsigned short timer;
  201. {
  202.     if (timer == TIMER_CALLBACK_TIMER) {
  203.     /*
  204.      * As long as we use the callback timer to keep track of time
  205.      * we shouldn't turn it off.
  206.      */
  207. #ifdef notdef
  208.      DISABLE_INTR();
  209.      *Mach_InterruptReg &= ~MACH_ENABLE_COUNTER0_INTR_LEVEL;
  210.      ENABLE_INTR();
  211. #endif
  212.     } else if (timer == TIMER_PROFILE_TIMER) {
  213.      DISABLE_INTR();
  214.      *Mach_InterruptReg &= ~MACH_ENABLE_COUNTER1_INTR_LEVEL;
  215.      ENABLE_INTR();
  216.     } else {
  217.     panic("Timer_TimerInactivate: unknown timer %d\n", timer);
  218.     }
  219.  
  220. }
  221.  
  222. /*
  223.  *----------------------------------------------------------------------
  224.  *
  225.  *  Timer_TimerServiceInterrupt --
  226.  *
  227.  *      This routine is called at every timer interrupt. 
  228.  *      It calls the timer callback queue handling if the callback timer 
  229.  *    expired and calls the profiling interrupt handling if the 
  230.  *    profile callback timer expired.
  231.  *
  232.  *  Results:
  233.  *    None.
  234.  *
  235.  *  Side Effects:
  236.  *    Routines on the timer queue may cause side effects. Profile
  237.  *    collect may take place. 
  238.  *    
  239.  *
  240.  *----------------------------------------------------------------------
  241.  */
  242.  
  243. int
  244. Timer_TimerServiceInterrupt(clientData, pc)
  245.     ClientData    clientData;            /* Really Counter number */
  246.     unsigned int    pc;        /* Only for sun4 version. */
  247.     register unsigned int junk;
  248.  
  249.     if ((unsigned int) clientData == TIMER_PROFILE_TIMER) {
  250.     /*
  251.      * Clear interrupt by reading limit register. 
  252.      */
  253.     junk = counterPtr->profileLimit;
  254.     TIMER_PROFILE_ROUTINE(pc);
  255. #       ifdef GATHER_STAT
  256.         timer_Statistics.profile++;
  257. #       endif
  258.     } else  if ((unsigned int) clientData == TIMER_CALLBACK_TIMER) {
  259.     /*
  260.      * Clear interrupt by reading limit register. 
  261.      */
  262.     junk = counterPtr->callBackLimit;
  263. #ifndef TOD_WORKING
  264.     /*
  265.      * Until we get the TOD chip working. Use the callback counter
  266.      * to keep track on time of day.
  267.      */
  268.      todCounter.microseconds += TIMER_CALLBACK_INTERVAL_APPROX;
  269. #ifdef ADJTIME
  270.      if (timer_AdjustDelta.microseconds || timer_AdjustDelta.seconds) {
  271.          register int adjust;
  272.  
  273.          if (timer_AdjustDelta.seconds == 0 &&
  274.              abs(timer_AdjustDelta.microseconds) < timer_TickAdjust) {
  275.          adjust = timer_AdjustDelta.microseconds;
  276.          } else {
  277.          adjust = timer_TickDelta;
  278.          }
  279.          todCounter.microseconds += adjust;
  280.          timer_AdjustDelta.microseconds -= adjust;
  281.          if (timer_TickDelta < 0) {
  282.          if (timer_AdjustDelta.microseconds > 0) {
  283.              ++timer_AdjustDelta.seconds;
  284.              timer_AdjustDelta.microseconds -= ONE_SECOND;
  285.          }
  286.          } else {
  287.          if (timer_AdjustDelta.microseconds < 0) {
  288.              --timer_AdjustDelta.seconds;
  289.              timer_AdjustDelta.microseconds += ONE_SECOND;
  290.          }
  291.          }
  292.      }
  293. #endif /* ADJTIME */
  294.      if (todCounter.microseconds > ONE_SECOND) {
  295.          todCounter.seconds++;
  296.          todCounter.microseconds -= ONE_SECOND;
  297.      }
  298. #endif
  299.     if (mach_KernelMode == 0) {
  300.         Proc_GetCurrentProc()->Prof_PC = pc;
  301.     }
  302.         TIMER_CALLBACK_ROUTINE(TIMER_CALLBACK_INTERVAL_APPROX, time);
  303.     } else {
  304.     panic("Timer_TimerServiceInterrupt: Unknown timer %d\n", 
  305.             (int) clientData);
  306.     }
  307. #ifdef lint
  308.     junk = junk;
  309. #endif
  310.     return 0;
  311. }
  312.  
  313. /*
  314.  *----------------------------------------------------------------------
  315.  *
  316.  * Timer_CounterInit --
  317.  *
  318.  *    Initializes the chip's free-running counters. Until we get the
  319.  *    TOD chip just use a counter updated by the CALL BACK interrupt
  320.  *    handler.
  321.  *
  322.  *    
  323.  * Results:
  324.  *    None.
  325.  *
  326.  * Side effects:
  327.  *    None.
  328.  *
  329.  *----------------------------------------------------------------------
  330.  */
  331.  
  332. void
  333. Timer_CounterInit()
  334. {
  335.     todCounter.seconds = 0;
  336.     todCounter.microseconds = 0;
  337. }
  338.  
  339. /* 
  340.  *----------------------------------------------------------------------
  341.  *
  342.  *  Timer_GetCurrentTicks --
  343.  *
  344.  *      Return microseconds since boot.
  345.  *
  346.  *  Results:
  347.  *    The system up-time in ticks.
  348.  *
  349.  *  Side effects:
  350.  *    None.
  351.  *
  352.  *----------------------------------------------------------------------
  353.  */
  354. void
  355. Timer_GetCurrentTicks(ticksPtr)
  356.     Timer_Ticks    *ticksPtr;    /* Buffer to place current time. */
  357. {
  358.     DISABLE_INTR();
  359.  
  360.     *ticksPtr = todCounter;
  361.  
  362.     ENABLE_INTR();
  363. }
  364.  
  365. /* 
  366.  *----------------------------------------------------------------------
  367.  *
  368.  *  Timer_GetInfo --
  369.  *
  370.  *      Dummy routine to dump timer state.
  371.  *
  372.  *  Results:
  373.  *    None.
  374.  *
  375.  *  Side effects:
  376.  *    None.
  377.  *
  378.  *----------------------------------------------------------------------
  379.  */
  380. /*ARGSUSED*/
  381. void
  382. Timer_TimerGetInfo(data)
  383.     ClientData    data;    /* Not used. */
  384. {
  385. }
  386.  
  387. /*
  388.  *----------------------------------------------------------------------
  389.  *
  390.  * TimerHardwareUniversalTimeInit --
  391.  *
  392.  *     Not implemented yet.
  393.  *
  394.  * Results:
  395.  *    None.
  396.  *
  397.  * Side effects:
  398.  *    None.
  399.  *
  400.  *----------------------------------------------------------------------
  401.  */
  402.  
  403. /*ARGSUSED*/
  404. void
  405. TimerHardwareUniversalTimeInit(timePtr, localOffsetPtr, DSTPtr)
  406.     Time *timePtr;        /* Buffer to hold universal time. */
  407.     int  *localOffsetPtr;    /* Buffer to hold local offset. */
  408.     Boolean *DSTPtr;        /* Buffer to hold DST allowed flag. */
  409. {
  410. }
  411.  
  412. /*
  413.  *----------------------------------------------------------------------
  414.  *
  415.  * TimerSetHardwareUniversalTime --
  416.  *
  417.  *    Not implemented yet.
  418.  *
  419.  * Results:
  420.  *    None.
  421.  *
  422.  * Side effects:
  423.  *    None.
  424.  *
  425.  *----------------------------------------------------------------------
  426.  */
  427.  
  428. /*ARGSUSED*/
  429. void
  430. TimerSetHardwareUniversalTime(timePtr, localOffset, DST)
  431.     Time *timePtr;        /* universal time. */
  432.     int  localOffset;        /* local offset. */
  433.     Boolean DST;        /* DST allowed flag. */
  434. {
  435. }
  436.